package org.spring.aicloud.controller;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.simpleframework.xml.core.Validate;
import org.spring.aicloud.entity.Discuss;
import org.spring.aicloud.entity.DiscussSupport;
import org.spring.aicloud.entity.User;
import org.spring.aicloud.entity.vo.CommentVO;
import org.spring.aicloud.entity.vo.DiscussVO;
import org.spring.aicloud.service.ICommentService;
import org.spring.aicloud.service.IDiscussService;
import org.spring.aicloud.service.IDiscussSupportService;
import org.spring.aicloud.service.IUserService;
import org.spring.aicloud.util.AppVariable;
import org.spring.aicloud.util.ResponseEntity;
import org.spring.aicloud.util.SecurityUtil;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.sql.Wrapper;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 讨论Controller
 */
@RestController
@RequestMapping("/discuss")
@Tag(name = "话题讨论控制器")
public class DiscussController {

    @Resource
    private IDiscussService discussService;
    @Resource
    private ThreadPoolTaskExecutor threadPool;
    @Resource
    private IUserService userService;
    @Resource
    private ICommentService commentService;
    @Resource
    private KafkaTemplate kafkaTemplate;
    @Resource
    private IDiscussSupportService discussSupportService;
    /**
     * 添加话题讨论
     */
    @RequestMapping("/add")
    public ResponseEntity addDiscuss(@Validate Discuss discuss) {
        discuss.setUid(SecurityUtil.getCurrentUser().getUid());
        boolean save = discussService.save(discuss);
        if (save) {
            return ResponseEntity.success(discuss);
        }
        return ResponseEntity.fail("添加失败");
    }

    /**
     * 获取我的讨论列表
     */
    @RequestMapping("/mylist")
    public ResponseEntity getMyDiscussList() {
        return ResponseEntity.success(discussService.list(
                Wrappers.lambdaQuery(Discuss.class)
                        .eq(Discuss::getUid, SecurityUtil.getCurrentUser().getUid())
                        .orderByDesc(Discuss::getDid)
        ));
    }

    /**
     * 获取列表
     * 带分页功能
     * @param pageIndex 页码
     * @param type 1、最热 2、最新 根据类型的不同进行排序的字段就不同
     */
    @RequestMapping("/list")
    public ResponseEntity list(Integer page,Integer type){
        //参数校验
        if (page==null || page<=0) {
            page = 1;
        }
        if (type==null || type<=0 || type>2){
            type = 1;
        }
        Page<Discuss> result = discussService.page(new Page<>(page, AppVariable.PAGE_SIZE),
                Wrappers.lambdaQuery(Discuss.class)
                        .orderByDesc((type == 1), Discuss::getSupportcount) //根据点赞数进行降序排序
                        .orderByDesc((type == 2), Discuss::getDid));//根据时间进行降序排序
        return ResponseEntity.success(result);
    }
    /**
     * 话题讨论的删除
     */
    @RequestMapping("/delete")
    public ResponseEntity deleteDiscuss(Long did) {
        if (did == null || did < 0) {
            return ResponseEntity.fail("参数错误");
        }
        boolean remove = discussService.remove(
                Wrappers.lambdaQuery(Discuss.class)
                        .eq(Discuss::getDid, did)
                        .eq(Discuss::getUid, SecurityUtil.getCurrentUser().getUid())
        );
        if (remove) {
            return ResponseEntity.success(remove);
        }
        return ResponseEntity.fail("删除失败");
    }

    /**
     * 查询话题详情
     */
    @RequestMapping("/detail")
    public ResponseEntity detail(Long did) throws ExecutionException, InterruptedException {
        if (did == null || did <= 0) {
            return ResponseEntity.fail("参数错误");
        }
        Discuss discuss = discussService.getById(did);
        if (discuss == null || discuss.getDid() <= 0) {
            return ResponseEntity.fail("话题不存在");
        }
        //discussService.saveOrUpdate()
        //添加阅读量
        threadPool.submit(()->{
            //1.更新数据库
            discussService.updateReadcount(did);
            //2.返回对象的阅读数+1
            discuss.setReadcount(discuss.getReadcount() + 1);
        });
        //查询到话题之后，要做两件事请
        //1.根据话题的uid去用户表里查询对应的用户名
        CompletableFuture<DiscussVO> task1 = CompletableFuture.supplyAsync(() -> {
            //利用hutool的BeanUtil进行对象转换
            DiscussVO discussVO = BeanUtil.toBean(discuss, DiscussVO.class);
            //根据话题的uid查询对应的用户
            User user = userService.getById(discuss.getUid());
            //判断用户是否存在
            if (user == null || user.getUid() <= 0) {
                return discussVO;
            }
            //如果存在用户，将用户名设置到discussVO上进行返回
            discussVO.setUsername(user.getUsername());
            return discussVO;
        }, threadPool);
        //2.根据话题的uid去评论表里查询对应的评论列表
        CompletableFuture<List<CommentVO>> task2 = CompletableFuture.supplyAsync(() -> {
            return commentService.getCommentList(discuss.getDid());
        }, threadPool);
        //等待任务1和2完成之后，进行数据的汇总
        CompletableFuture.allOf(task1, task2);
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("discuss", task1.get());
        hashMap.put("commentlist", task2.get());
        return ResponseEntity.success(hashMap);
    }

    /**
     * 话题讨论点赞事件
     * 前端点击点赞按钮，访问、support
     * 这个方法只需要将传递过来的话题id发送到消息队列里面即可
     */
    @RequestMapping("/support")
    public ResponseEntity support(Long did) {
        if (did==null || did<=0){
            return ResponseEntity.fail("参数错误");
        }
        Long uid = SecurityUtil.getCurrentUser().getUid();
        String data = did+"_"+uid;
        kafkaTemplate.send(AppVariable.DISCUSS_SUPPORT_TOPIC,data);
        return ResponseEntity.success(true);
    }

    /**
     * 监听kafka中的话题点赞事件
     *
     */
    @KafkaListener(topics = AppVariable.DISCUSS_SUPPORT_TOPIC)
    public void listen(String data, Acknowledgment acknowledgment){
        //1.判断此用户是否已经针对当前话题点过赞了
        //从SpringSecurity中是获取不到的，因为这个方式是kafka的上下文，不再是请求的上下文了。
        //那获取uid只能让生产者发送过来了.
        //Long uid = SecurityUtil.getCurrentUser().getUid();
        Long did = Long.parseLong(data.split("_")[0]);
        Long uid = Long.parseLong(data.split("_")[1]);
        //根据uid和did进行查询
        QueryWrapper<DiscussSupport> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",uid);
        wrapper.eq("did",did);
        DiscussSupport discussSupport = discussSupportService.getOne(wrapper);
        //2.如果已经点过赞了，则返回
        if (discussSupport==null){
            //3.如果没有点过赞，修改话题讨论表的点赞数
            int i = discussService.updateSupportCount(did);
            if (i>0){
                //4.并且，在点赞详情表里插入一条对应的数据
                DiscussSupport discussSupport2 = new DiscussSupport();
                discussSupport2.setUid(uid);
                discussSupport2.setDid(did);
                boolean save = discussSupportService.save(discussSupport2);
                if (save) {
                    //手动确认消息已消费
                    acknowledgment.acknowledge();
                }
            }
        }else {
            //已经点赞过了，所以直接确认消费即可
            acknowledgment.acknowledge();
        }
    }



}

